import def from './def'
// 得到Array.prototype
const arrayPrototype = Array.prototype

// 以Array.prototype为原型创建对象arrayMethods,并暴露
export const arrayMethods = Object.create(arrayPrototype)

// 要不改下的7个数组方法
const methodsNeedToPath = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse',
]

methodsNeedToPath.forEach((methodName) => {
  // 备份原来的方法，因为这七个方法的功能不能被剥夺
  const original = arrayPrototype[methodName]
  // 定义新的方法
  def(
    arrayMethods,
    methodName,
    function () {
      // 恢复原来的功能
      // console.log('对数组的操作', arguments)
      const result = original.apply(this, arguments)
      // 将这个类数组对象变成数组
      const args = [...arguments] // 例如 obj.c.splice(2, 1, [99, 12])， arguments就是数组[2, 1, [99, 12]]
      // 把这个数组身上的__ob__属性取出来， __ob__已经被添加了，为什么已经被添加了？因为数组肯定不是最高层，比如obj.g属性时数组，obj不能是数组，第一次遍历obj这个对象的第一层的时候，已经给g属性（就是这个数组）添加了__ob__属性。
      const ob = this.__ob__
      // 有三种方法push\unshift\splice能够插入新项，现在要把插入的新项也要变为observe的
      let inserted = []
      switch (methodName) {
        case 'push':
          break
        case 'unshift':
          inserted = args
          break
        case 'splice':
          // splice 第三个参数以后都是插入的新项
          inserted = args.slice(2)
          break
      }
      // 判断有没有要插入的新项，让新项也是响应式
      if (inserted) {
        ob.observeArray(inserted)
      }
      ob.dep.notify()
      return result
    },
    false
  )
})
